package com.dhcc.core.modules.system.controller;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.naming.NoPermissionException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import com.baomidou.mybatisplus.plugins.Page;
import com.dhcc.core.framework.annotion.BussinessLog;
import com.dhcc.core.framework.annotion.CacheClear;
import com.dhcc.core.framework.annotion.Permission;
import com.dhcc.core.framework.base.controller.BaseController;
import com.dhcc.core.framework.constant.Const;
import com.dhcc.core.framework.constant.state.ManagerStatus;
import com.dhcc.core.framework.datascope.DataScope;
import com.dhcc.core.framework.exception.BizException;
import com.dhcc.core.framework.exception.BizExceptionEnum;
import com.dhcc.core.framework.result.R;
import com.dhcc.core.framework.result.page.PageFactory;
import com.dhcc.core.framework.security.ShiroKit;
import com.dhcc.core.framework.util.CommonUtil;
import com.dhcc.core.framework.util.DateUtil;
import com.dhcc.core.modules.system.cache.position.PositionCache;
import com.dhcc.core.modules.system.cache.user.IUserCache;
import com.dhcc.core.modules.system.entity.Position;
import com.dhcc.core.modules.system.entity.User;
import com.dhcc.core.modules.system.service.IUserService;
import com.dhcc.core.modules.system.transfer.DeptRoleDto;
import com.dhcc.core.modules.system.transfer.UserDto;
import com.dhcc.core.modules.system.vo.ExportUserVo;
import com.dhcc.core.modules.system.warpper.UserWarpper;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.poi.excel.BigExcelWriter;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;

/**
 * 系统用户控制器
 * 
 * @ClassName: UserController
 * @Description: TODO
 * @author: cyf
 * @date: 2018年1月2日 上午10:33:06
 */
@Controller
@RequestMapping("${sys.backendPath}/user")
public class UserController extends BaseController {

    private static String PREFIX = "/backend/system/user/";

    @Autowired
    private IUserService userService;
    
    @Value("${sys.orgFullName}")
    private String orgFullName;

    /**
     * 跳转到查看用户列表的页面
     */
    @RequestMapping
    public String index() {
        return PREFIX + "user.html";
    }

    /**
     * 跳转到查看用户列表的页面
     */
    @Permission("user:add")
    @RequestMapping("/to_add")
    public String addView() {
        return PREFIX + "user_add.html";
    }

    /**
     * 跳转到编辑用户页面
     */
    @Permission("user:update")
    @RequestMapping("/to_edit/{userId}")
    public String userEdit(@PathVariable Long userId, Model model) {
        if (CommonUtil.isEmpty(userId)) {
            throw new BizException(BizExceptionEnum.REQUEST_NULL);
        }
        User user = this.userService.selectById(userId);
        List<DeptRoleDto> deptRoles = this.userService.getDeptRoles(userId);
        Position position =  new Position();
        if(CommonUtil.isNotEmpty(user.getPositionId())){
        	 position.setId(Long.parseLong(user.getPositionId().toString()));
             position.setName(PositionCache.me().getPositionNameById(position.getId()));
        }
        model.addAttribute(user);
        model.addAttribute("deptRoles",deptRoles);
        model.addAttribute(position);
        return PREFIX + "user_edit.html";
    }

    /**
     * 跳转到查看用户详情页面
     */
    @RequestMapping("/info")
    public String userInfo(Model model) {
        Long userId = ShiroKit.getUser().getId();
        if (CommonUtil.isEmpty(userId)) {
            throw new BizException(BizExceptionEnum.REQUEST_NULL);
        }
        User user = this.userService.selectById(userId);
        List<DeptRoleDto> deptRoles = this.userService.getDeptRoles(userId);
        Position position =  new Position();
        if(CommonUtil.isNotEmpty(user.getPositionId())){
        	position.setId(Long.parseLong(user.getPositionId().toString()));
            position.setName(PositionCache.me().getPositionNameById(position.getId()));
        }
        model.addAttribute(user);
        model.addAttribute("deptRoles",deptRoles);
        model.addAttribute(position);
        return PREFIX + "user_view.html";
    }
    
    /**
     * 跳转到查看用户详情页面，有关闭按钮
     */
    @RequestMapping("/info_cancel")
    public String userInfoC(Model model) {
        Long userId = ShiroKit.getUser().getId();
        if (CommonUtil.isEmpty(userId)) {
            throw new BizException(BizExceptionEnum.REQUEST_NULL);
        }
        User user = this.userService.selectById(userId);
        List<DeptRoleDto> deptRoles = this.userService.getDeptRoles(userId);
        Position position =  new Position();
        position.setId(Long.parseLong(user.getPositionId().toString()));
        position.setName(PositionCache.me().getPositionNameById(position.getId()));
        model.addAttribute(user);
        model.addAttribute("deptRoles",deptRoles);
        model.addAttribute(position);
        model.addAttribute("emptyCancel", "cancel");
        return PREFIX + "user_view.html";
    }

    /**
     * 跳转到修改密码界面
     */
    @RequestMapping("/to_password")
    public String chPwd() {
        return PREFIX + "user_chpwd.html";
    }
    
    /**
     * 跳转到修改密码界面,有关闭按钮
     */
    @RequestMapping("/to_password_cancel")
    public String chPwdC(Model model) {
    	model.addAttribute("emptyCancel", "cancel");
        return PREFIX + "user_chpwd.html";
    }

    /**
     * 修改当前用户的密码
     */
	@RequestMapping("/update_password")
    @ResponseBody
    public Object changePwd(@RequestParam String oldPwd, @RequestParam String newPwd, @RequestParam String rePwd) {
        if (!newPwd.equals(rePwd)) {
        	try {
        		throw new BizException(BizExceptionEnum.TWO_PWD_NOT_MATCH);
			} finally {
				return R.error(500,"两次输入密码不一致");
			}
        }
        if (newPwd.length()==0&&rePwd.length()==0) {
        	try {
        		throw new BizException(BizExceptionEnum.NEW_PWD_EMPTY);
        	}finally {
        		return R.error(500,"新密码不能为空");
			}
        }
        Long userId = ShiroKit.getUser().getId();
        User user = userService.selectById(userId);
        String oldMd5 = ShiroKit.md5(oldPwd, user.getSalt());
        if (user.getPassword().equals(oldMd5)) {
            String newMd5 = ShiroKit.md5(newPwd, user.getSalt());
            user.setPassword(newMd5);
            user.updateById();
            return R.ok();
        } else {
			try {
				throw new BizException(BizExceptionEnum.OLD_PWD_NOT_RIGHT);
			}finally {
				return R.error(500,"原密码不正确");
			}
        }
    }

    /**
     * 查询用户列表
     */
    @SuppressWarnings("unchecked")
    @RequestMapping("/list")
    @Permission("user:list")
    @ResponseBody
    public Object list(@RequestParam(required = false) String userName,
            @RequestParam(required = false) String beginTime, @RequestParam(required = false) String endTime,
            @RequestParam(required = false) Long deptid) {
        Page<User> page = new PageFactory<User>().defaultPage();
        if (ShiroKit.isAdmin()) {//判断是否为超级管理员
        	List<Map<String, Object>> result = userService.selectUsers(null,page, userName, beginTime, endTime, deptid);
            page.setRecords((List<User>) new UserWarpper(result).warp());
		}else {
			DataScope dataScope = new DataScope(ShiroKit.getDepDataScope());
			List<Map<String, Object>> result = userService.selectUsers(dataScope,page, userName, beginTime, endTime, deptid);
            page.setRecords((List<User>) new UserWarpper(result).warp());
		}
        
        return R.packForBT(page);
    }

    /**
     * 添加用户
     */
    @RequestMapping("/add")
    @BussinessLog(value = "添加用户")
    @Permission("user:add")
    @ResponseBody
    @CacheClear(IUserCache.CACHE_NAME)
    public R add(@Valid UserDto user,@RequestParam String deptRole, BindingResult result) {
        if (result.hasErrors()) {
            throw new BizException(BizExceptionEnum.REQUEST_NULL);
        }
        userService.addUser(user,deptRole);
        return R.ok();
    }

    /**
     * 修改用户
     *
     * @throws NoPermissionException
     */
    @RequestMapping("/edit")
    @Permission("user:update")
    @BussinessLog(value = "修改用户")
    @ResponseBody
    @CacheClear(IUserCache.CACHE_NAME)
    public R edit(@Valid UserDto user,@RequestParam String deptRole, BindingResult result) throws NoPermissionException {
        if (result.hasErrors()) {
            throw new BizException(BizExceptionEnum.REQUEST_NULL);
        }
        this.userService.updateUser(user,deptRole);
        return R.ok();
    }

    /**
     * 删除用户（逻辑删除）
     */
    @RequestMapping("/delete")
    @BussinessLog(value = "删除用户")
    @Permission("user:delete")
    @ResponseBody
    @CacheClear(IUserCache.CACHE_NAME)
    public R delete(@RequestParam Long userId) {
        if (CommonUtil.isEmpty(userId)) {
            throw new BizException(BizExceptionEnum.REQUEST_NULL);
        }
        // 不能删除超级管理员
        if (userId.equals(Const.ADMIN_ID)) {
            throw new BizException(BizExceptionEnum.CANT_DELETE_ADMIN);
        }
        this.userService.deleteUser(userId);
        //this.userService.setStatus(userId, ManagerStatus.DELETED.getCode());
        return R.ok();
    }

    /**
     * 查看用户详情
     */
    @RequestMapping("/view/{userId}")
    @ResponseBody
    public User view(@PathVariable Long userId) {
        if (CommonUtil.isEmpty(userId)) {
            throw new BizException(BizExceptionEnum.REQUEST_NULL);
        }
        return this.userService.selectById(userId);
    }

    /**
     * 重置用户的密码
     */
    @RequestMapping("/reset")
    @BussinessLog(value = "重置用户密码")
    @Permission("user:reset")
    @ResponseBody
    public R reset(@RequestParam Long userId) {
        if (CommonUtil.isEmpty(userId)) {
            throw new BizException(BizExceptionEnum.REQUEST_NULL);
        }
        User user = this.userService.selectById(userId);
        user.setSalt(ShiroKit.getRandomSalt(5));
        user.setPassword(ShiroKit.md5(Const.DEFAULT_PWD, user.getSalt()));
        this.userService.updateById(user);
        return R.ok();
    }

    /**
     * 冻结用户
     */
    @RequestMapping("/freeze")
    @BussinessLog(value = "冻结用户")
    @Permission("user:freeze")
    @ResponseBody
    @CacheClear(IUserCache.CACHE_NAME)
    public R freeze(@RequestParam Long userId) {
        if (CommonUtil.isEmpty(userId)) {
            throw new BizException(BizExceptionEnum.REQUEST_NULL);
        }
        // 不能冻结超级管理员
        if (userId.equals(Const.ADMIN_ID)) {
            throw new BizException(BizExceptionEnum.CANT_FREEZE_ADMIN);
        }
        this.userService.setStatus(userId, ManagerStatus.FREEZED.getCode());
        return R.ok();
    }

    /**
     * 解除冻结用户
     */
    @RequestMapping("/unfreeze")
    @BussinessLog(value = "解除冻结用户")
    @Permission("user:unfreeze")
    @ResponseBody
    @CacheClear(IUserCache.CACHE_NAME)
    public R unfreeze(@RequestParam Long userId) {
        if (CommonUtil.isEmpty(userId)) {
            throw new BizException(BizExceptionEnum.REQUEST_NULL);
        }
        this.userService.setStatus(userId, ManagerStatus.OK.getCode());
        return R.ok();
    }
    /**
     * 导出用户
     * @Title: export 
     * @Description: TODO
     * @param userName
     * @param beginTime
     * @param endTime
     * @param deptid
     * @param request
     * @param response
     * @return: void
     */
    @Permission("user:export")
    @RequestMapping("/export")
    public void exportUsers(@RequestParam(required = false) String userName,
            @RequestParam(required = false) String beginTime, @RequestParam(required = false) String endTime,
            @RequestParam(required = false) Long deptid,
            HttpServletRequest request, HttpServletResponse response) {
        List<ExportUserVo> result = this.userService.exportUsers(userName, beginTime, endTime, deptid);

        // 通过工具类创建writer，默认创建xls格式
        BigExcelWriter writer = (BigExcelWriter) ExcelUtil.getBigWriter();
        // 一次性写出内容，使用默认样式
        if (CommonUtil.isNotEmpty(result)) {
            ArrayList<Map<String, Object>> rows = CollUtil.newArrayList();
            for (ExportUserVo obj : result) {
                Map<String, Object> row = new LinkedHashMap<>();
                row.put("部门编码", obj.getDeptCode());
                row.put("部门名称", obj.getDeptName());
                row.put("部门全称", obj.getDeptFullname());
                row.put("登录名", obj.getLoginName());
                row.put("工号", obj.getUserCode());
                row.put("姓名", obj.getName());
                row.put("生日", CommonUtil.isEmpty(obj.getBirthday()) ? "" : DateUtil.getDay(obj.getBirthday()));
                row.put("性别", obj.getSex());
                row.put("Email", obj.getEmail());
                row.put("电话", obj.getPhone());
                row.put("职务编码", obj.getPositionCode());
                row.put("职务名称", obj.getPositionName());
                rows.add(row);
            }
            writer.write(rows);
            writer.setColumnWidth(2, 15);
            writer.setColumnWidth(6, 15);
            writer.setColumnWidth(8, 20);
            writer.setColumnWidth(9, 15);
        } else {
            List<String> row = CollUtil.newArrayList("无数据");
            List<List<String>> rows = new ArrayList<List<String>>();
            rows.add(row);
            writer.write(rows);
        }

        ServletOutputStream out = null;
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
            String fileName = "用户_" + sdf.format(new Date()) + ".xlsx";
            response.setContentType("application/vnd.ms-excel;charset=utf-8");
            response.setHeader("Content-Disposition", "attachment;filename=" + new String(fileName.getBytes("GBK"),"ISO8859_1"));
            out = response.getOutputStream();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            writer.flush(out);
            // 关闭writer，释放内存
            writer.close();
        }
    }

    /**
     * 跳转到导入用户的页面
     */
    @Permission("user:import")
    @RequestMapping("/to_import")
    public String toImport() {
        return PREFIX + "import.html";
    }
    /**
     * 导入用户
     */
    @Permission("user:import")
    @RequestMapping(method = RequestMethod.POST, path = "/import")
    @ResponseBody
    public R importUsers(@RequestPart("file") MultipartFile file) {
        ExcelReader reader;
        try {
            reader = ExcelUtil.getReader(file.getInputStream());
            List<List<Object>> all = reader.read();
            this.userService.importUsers(all);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            System.out.println(e.getMessage());
            return R.error(e.getMessage());
        }
        return R.ok();
    }
}
